using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Media3D;
using System.Windows.Media.Effects;
using System.Windows.Media.Animation;
using NewtonDynamics;


//TODO The world freezes. Has to do with moving the car.
namespace WPFPhysics1
{
	/// <summary>
	/// Interaction logic for World.xaml
	/// </summary>

    public enum BodyActionType { none, remove, addimpulse, dragstart, dragstop,rotate,rotatestop };
  
	public partial class World : UserControl, INotifyPropertyChanged
	{
        Bodies bodies;

		public World()
		{
			InitializeComponent();

			CompositionTarget.Rendering += new EventHandler( CompositionTarget_Rendering );
			base.SizeChanged += new SizeChangedEventHandler( World_SizeChanged );
;

		}


		/// <summary>
		/// Frame rendering event
		/// </summary>
		/// <param name="sender">Sender</param>
		/// <param name="e">Event arguments</param>
		void CompositionTarget_Rendering( object sender, EventArgs e )
		{
			bodies = DataContext as Bodies;
			if ( bodies != null ) bodies.Update();
		}

		/// <summary>
		/// Size changed
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void World_SizeChanged( object sender, SizeChangedEventArgs e )
		{
			if ( PropertyChanged != null ) PropertyChanged( this, new PropertyChangedEventArgs( "ScaleTransform" ) );
		}

		/// <summary>
		/// Get scale transformation
		/// </summary>
		public System.Windows.Media.Matrix ScaleTransform
		{
			get
			{
				bodies = DataContext as Bodies;

				if ( bodies != null )
				{
					double height = ActualHeight;
					double width = height * ( bodies.WorldWidth / bodies.WorldHeight );

					Matrix matrix = Matrix.Identity;

					// Scale world units to display units
					matrix.Scale( width / bodies.WorldWidth, height / bodies.WorldHeight );

					// Adjust for aspect ratio (center appropriately)
					matrix.Translate( ( ActualWidth - width ) / 2, ( ActualHeight - height ) / 2 );

					// Center on display
					matrix.Translate( width / 2, height / 2 );

					return matrix;
				}

				return Matrix.Identity;
			}
		}

		#region INotifyPropertyChanged Members

		public event PropertyChangedEventHandler PropertyChanged;

		#endregion

        //Rohit Addition

        private void myMouseButtonHandler(object sender, MouseButtonEventArgs e)
        {

            Shape clickedShape = sender as Shape;


            if (e.ChangedButton == MouseButton.Left)
            {
                bodies.mouseDownBodyId = clickedShape.Uid;
                // search for the ID and dispose
                if (e.ButtonState == MouseButtonState.Released)
                {
                    bodies.UIBodyAction();
                    bodies.BodyAction = BodyActionType.none;
                    bodies.mouseDownBodyId = "";
                }
                else
                {
                    bodies.mouseLocationAtClick = bodies.mouseCurrentLocation;
                    bodies.BodyAction = BodyActionType.remove;
                }
            }
            else
            {
                if (e.ChangedButton == MouseButton.Right)
                {
                    bodies.mouseDownBodyId = clickedShape.Uid;
                    if (e.ButtonState == MouseButtonState.Pressed)
                    {
                        bodies.mouseLocationAtClick = bodies.mouseCurrentLocation;
                        bodies.BodyAction = BodyActionType.dragstart;
                    }
                    else
                    {
                        if (bodies.BodyAction == BodyActionType.dragstart)
                        {
                            bodies.BodyAction = BodyActionType.dragstop;
                            bodies.UIBodyAction();
                        }
                    }
                }
                else
                {
                    if (e.ChangedButton == MouseButton.Middle)
                    {
                        if (e.ButtonState == MouseButtonState.Pressed)
                        {
                            bodies.mouseWheelBodyId = clickedShape.Uid;
                        }
                    }
                }

            }
        }

        private void myMouseMoveHandler(object sender, MouseEventArgs e)
        {

            // if a body has been selected then any movement indicates that impulse needs
            // to be added to the body

            bodies.mouseCurrentLocation = e.GetPosition(Application.Current.MainWindow);
            bodies.mouseLocationAtClickRelativeToObject = e.GetPosition((Shape)sender);

            if (bodies.mouseCurrentLocation != bodies.mouseLocationAtClick)
            {
                if (bodies.BodyAction== BodyActionType.remove)
                {
                    bodies.BodyAction = BodyActionType.addimpulse;
                } else {
                    if (bodies.BodyAction == BodyActionType.dragstart)
                    {
       
                        bodies.UIBodyAction();
                    }
                }

            }
        }

        private void myMouseEnterHandler(object sender, MouseEventArgs e)
        {

            // as soon as mouse enters the rigid body the action is set to none
            if ((bodies.BodyAction != BodyActionType.dragstart) && (bodies.BodyAction !=BodyActionType.rotate))
            {
                bodies.BodyAction = BodyActionType.none;
                bodies.mouseDownBodyId = "";
                bodies.mouseWheelBodyId = "";
            }

            //Animate the shape
            Shape clickedShape = sender as Shape;

            DoubleAnimation danim = new DoubleAnimation();
            danim.From = clickedShape.Fill.Opacity;
            danim.To = clickedShape.Fill.Opacity / 5;
            danim.AutoReverse = true;
            danim.RepeatBehavior = RepeatBehavior.Forever;
            clickedShape.BeginAnimation(Shape.OpacityProperty, danim);
        }

        private void myMouseLeaveHandler(object sender, MouseEventArgs e)
        {
             stopAnimation(sender as Shape);

            // if a body is being dragged, then continue to drag
            // if it is in impulse mode, then complete the action

            if (bodies.BodyAction == BodyActionType.addimpulse)
            {
                bodies.UIBodyAction();
                bodies.BodyAction = BodyActionType.none;
                bodies.mouseDownBodyId = "";
            }

        }

        private void stopAnimation(Shape clickedShape)
        {
                DoubleAnimation danim = new DoubleAnimation();
                danim.From = clickedShape.Fill.Opacity;
                danim.To = clickedShape.Fill.Opacity;
                clickedShape.BeginAnimation(Shape.OpacityProperty, danim, HandoffBehavior.SnapshotAndReplace);
        }

   }
}